home *** CD-ROM | disk | FTP | other *** search
/ Computer Select (Limited Edition) / Computer Select.iso / dobbs / v17n02 / turtle.exe / TCMDS.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-03  |  18.2 KB  |  837 lines

  1. /*****************************************************************
  2.  *                                                               *
  3.  * TCMDS.C      XCI commands for TURTLE.EXE                      *
  4.  *                                                               *
  5.  * Al Williams                                                   *
  6.  *                                                               *
  7.  *****************************************************************
  8. /* Assume large model */
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <malloc.h>
  13. #include <dos.h>
  14. #include <conio.h>
  15. #include <string.h>
  16. #include <graph.h>
  17. #include <ctype.h>
  18. #include <direct.h>
  19. #define INCL_DOSPROCESS
  20. #include <phapi.h>
  21. #include <float.h>
  22.  
  23. #include "turtle.h"
  24. #include "xci.h"
  25.  
  26. /* tokens for commands */
  27. char *tokens[10];
  28.  
  29. #define NOARG if (parse(cmds)!=0) synerr;
  30. #define synerr { _synerr(); return; }
  31.  
  32. /* syntax error */
  33. _synerr()
  34.   {
  35.   printf("Syntax error\n");
  36.   }
  37.  
  38. /* parse a command line into the tokens array
  39.    return the number of tokens */
  40. int parse(char *cmd)
  41.   {
  42.   int i;
  43.   char *t;
  44.   t=tokens[i=0]=strtok(cmd," \t\n");
  45.   while (t&&i<9)
  46.     {
  47.     t=strtok(NULL," \t\n");
  48.     if (t)
  49.       {
  50.       if (i==9) return -1;
  51.       tokens[++i]=t;
  52.       }
  53.     }
  54.   return tokens[0]?i+1:0;
  55.   }
  56.  
  57.  
  58.  
  59. /* Get a number from token. It must be between lo and hi
  60.    (unless lo==hi) if it is preceeded by a + or a -, it
  61.    is added to rel the final value is stored in *val)
  62.    returns 1 if out of range, 0 if OK */
  63. int _far _loadds _export getval(char *token,int rel,
  64.                                 int lo, int hi,int *val)
  65.   {
  66.   int flag=0;    /* add value to rel? */
  67.   if (*token=='+') flag=1;
  68.   if (*token=='-') flag=-1;
  69.   if (flag) token++;
  70.  
  71. /* evaluate expression */
  72.   *val=evalexpr(token);
  73.  
  74. /* adjust value relative */
  75.   if (flag==-1) *val=-*val;
  76.   if (flag) *val+=rel;
  77.  
  78. /* check range */
  79.   if (lo!=hi&&(*val<lo||*val>hi))
  80.     {
  81.     printf("Bad value: %d. Use %d to %d\n",*val,lo,hi);
  82.     return 1;
  83.     }
  84.   return 0;
  85.   }
  86.  
  87. /* Get xcoordinate */
  88. #define getxco(token,val) \
  89.    getval(token,appdata.graphxy.xcoord,-999,999,val)
  90.  
  91. /* Get y coordinate */
  92. #define getyco(token,val) \
  93.    getval(token,appdata.graphxy.ycoord,-999,999,val)
  94.  
  95. /* get heading */
  96. #define gethead(token,val) \
  97.    (getval(token,appdata.heading,0,0,val)%360)
  98.  
  99. /* get color value */
  100. #define getcolor(token,val) \
  101.    getval(token,appdata.color,0,255,val)
  102.  
  103.  
  104. /* run a DOS command without XCI interfering with ^C */
  105. static void rundos(char *line)
  106.    {
  107.    int brkstatus=xci_defaultbrk;
  108.    xci_defaultbrk=0;
  109.    if (system(line)==-1)
  110.       {
  111.       printf("Can't execute: %s\n",line);
  112.       }
  113.    xci_defaultbrk=brkstatus;
  114.    }
  115.  
  116.  
  117.  
  118. /* EDIT file */
  119. XCICMD editcmd(int cmd, char far *cmds,struct udata *data)
  120.   {
  121.   char cmdline[129];
  122.   char *cmdst;
  123.   unsigned long stat;
  124.   if (cmd)
  125.     {
  126.     printf("Edit a file\n");
  127.     return;
  128.     }
  129. /* Get editor name from $TURTLEEDIT */
  130.   cmdst=getenv("TURTLEEDIT");
  131. /* If not specified, use DOS 5 EDIT command */
  132.   if (!cmdst) cmdst="EDIT";
  133. /* build command line */
  134.   strcpy(cmdline,cmdst);
  135.   strcat(cmdline," ");
  136.   strcat(cmdline,cmds);
  137.   rundos(cmdline);
  138.   }
  139.  
  140.  
  141. /* DOS directory */
  142. XCICMD dircmd(int cmd, char far *cmds,struct udata *data)
  143.   {
  144.   char cmdline[129];
  145.   unsigned long stat;
  146.   if (cmd)
  147.     {
  148.     printf("DOS directory\n");
  149.     return;
  150.     }
  151.   strcpy(cmdline,"DIR ");
  152.   strcat(cmdline,cmds);
  153.   rundos(cmdline);
  154.   }
  155.  
  156.  
  157. /* DOS command */
  158. XCICMD doscmd(int cmd, char far *cmds,struct udata *data)
  159.   {
  160.   char cmdline[129];
  161.   char *cmdst;
  162.   int rc;
  163.   unsigned long stat;
  164.   if (cmd)
  165.     {
  166.     printf("Run DOS or a DOS command\n");
  167.     return;
  168.     }
  169.   rundos(*cmds?cmds:"COMMAND");  /* quick, yet dirty */
  170.   }
  171.  
  172. /* change directory */
  173. XCICMD cdcmd(int cmd, char far *cmds,struct udata *data)
  174.   {
  175.   int buf;
  176.   if (cmd)
  177.     {
  178.     printf("Change the current working directory\n");
  179.     return;
  180.     }
  181.   if (chdir(cmds))
  182.      printf("Error changing directory\n");
  183.   }
  184.  
  185.  
  186. /* Get text xy coordinate */
  187. struct rccoord getxy()
  188.   {
  189.   struct rccoord rc;
  190.   union REGS r;
  191.   r.h.ah=3;
  192.   r.h.bh=0;
  193.   int86(0x10,&r,&r);
  194.   rc.row=r.h.dh;
  195.   rc.col=r.h.dl;
  196.   return rc;
  197.   }
  198.  
  199. /* move text cursor to x,y */
  200. gotoxy(int x,int y)
  201.   {
  202.   union REGS r;
  203.   r.h.ah=2;
  204.   r.h.bh=0;
  205.   r.h.dh=y;
  206.   r.h.dl=x;
  207.   int86(0x10,&r,&r);
  208.   }
  209.  
  210.  
  211. /* Graphics buffer */
  212. char _gbuf[64000];
  213.  
  214. /* Initilize pointers */
  215. setptr(struct udata *data)
  216.   {
  217.   int rseg;
  218.  
  219. /* buffer 10 stores pointer to graphics buffer */
  220.   data->store[10]=data->gbuf=_gbuf;
  221.  
  222. /* Get PM pointer to VGA screen */
  223.   DosMapRealSeg(0xa000,(unsigned)64000,&rseg);
  224. /* buffer 11 points to screen */
  225.   data->store[11]=data->gptr=MAKEP(rseg,0);
  226.  
  227. /* Get PM pointer to text screen */
  228.   DosMapRealSeg(0xb800,4000,&rseg);
  229.   data->tptr=MAKEP(rseg,0);
  230.   }
  231.  
  232.  
  233. /* switch mode to graphics */
  234. void gograph(struct udata *data)
  235.   {
  236. /* Init if required */
  237.   if (!data->gptr) setptr(data);
  238. /* if already in graphics, quit */
  239.   if (data->textgraph) return;
  240. /* save text screen */
  241.   memcpy(data->tbuf,data->tptr,4000);
  242. /* save cursor position */
  243.   data->textxy=getxy();
  244.  
  245. /* switch modes */
  246.   _setvideomode(_MRES256COLOR);
  247. /* set colors */
  248.   _setcolor(data->color);
  249.   _setbkcolor(data->backcolor);
  250. /* restore graphics position */
  251.   _moveto(data->graphxy.xcoord,data->graphxy.ycoord);
  252. /* restore contents of buffer */
  253.   memcpy(data->gptr,data->gbuf,(unsigned)64000);
  254.   }
  255.  
  256.  
  257. /* Switch to text mode */
  258. void gotext(struct udata *data)
  259.   {
  260. /* INIT if required */
  261.   if (!data->gptr) setptr(data);
  262. /* If already in text mode quit */
  263.   if (data->textgraph) return;
  264. /* store graphics screen */
  265.   memcpy(data->gbuf,data->gptr,(unsigned)64000);
  266. /* save position */
  267.   data->graphxy=_getcurrentposition();
  268.  
  269. /* swtich to text mode */
  270.   _setvideomode(_TEXTC80);
  271. /* restore text screen */
  272.   memcpy(data->tptr,data->tbuf,4000);
  273. /* restore text cursor */
  274.   gotoxy(data->textxy.col,data->textxy.row);
  275.   }
  276.  
  277.  
  278. /* move turtle to x,y */
  279. turmove(int x,int y)
  280.   {
  281. /* Since this function is built in, its OK to use appdata
  282.    directly. A DLL command would need the pointer passed
  283.    to it by XCI */
  284. /* Draw or move based on mode */
  285.   if (appdata.mode)
  286.     _moveto(x,y);
  287.   else
  288.     _lineto(x,y);
  289.   }
  290.  
  291. /* Show graphics screen */
  292. XCICMD showcmd(int cmd, char far *cmds,struct udata *data)
  293.   {
  294.   int n;
  295.   if (cmd)
  296.     {
  297.     printf("Show graphics screen\n");
  298.     return;
  299.     }
  300.   n=parse(cmds);
  301.   if (n>1) { printf("%d\n",n); synerr; return; }
  302.   if (!n)
  303.     {
  304.     gograph(data);
  305.     if (!getch()) getch();
  306.     gotext(data);
  307.     return;
  308.     }
  309.   if (!stricmp(tokens[0],"ON"))
  310.       {
  311.       if (!data->textgraph)
  312.         {
  313.         gograph(data);
  314.         data->textgraph=1;
  315.         }
  316.       return;
  317.       }
  318.   if (!stricmp(tokens[0],"OFF"))
  319.       {
  320.       if (data->textgraph)
  321.         {
  322.         data->textgraph=0;
  323.         gotext(data);
  324.         }
  325.       return;
  326.       }
  327.     synerr;
  328.   }
  329.  
  330.  
  331. /* SETX */
  332. XCICMD setxcmd(int cmd, char far *cmds,struct udata *data)
  333.   {
  334.   int newx;
  335.   if (cmd)
  336.     {
  337.     printf("Set X coordinate\n");
  338.     return;
  339.     }
  340.   if (parse(cmds)!=1) synerr;
  341.   if (getxco(tokens[0],&newx)) return;
  342.   gograph(data);
  343.   turmove(data->graphxy.xcoord=newx,data->graphxy.ycoord);
  344.   data->realx=(double)newx;
  345.   gotext(data);
  346.   }
  347.  
  348. /* SETY */
  349. XCICMD setycmd(int cmd, char far *cmds,struct udata *data)
  350.   {
  351.   int newy;
  352.   if (cmd)
  353.     {
  354.     printf("Set Y coordinate\n");
  355.     return;
  356.     }
  357.   if (parse(cmds)!=1) synerr;
  358.   if (getyco(tokens[0],&newy)) return;
  359.   gograph(data);
  360.   data->realy=(double)newy;
  361.   turmove(data->graphxy.xcoord,data->graphxy.ycoord=newy);
  362.   gotext(data);
  363.   }
  364.  
  365.  
  366. /* SET both X and Y */
  367. XCICMD setxycmd(int cmd, char far *cmds,struct udata *data)
  368.   {
  369.   int newx,newy;
  370.   if (cmd)
  371.     {
  372.     printf("Set X & Y coordinates\n");
  373.     return;
  374.     }
  375.   if (parse(cmds)!=2) synerr;
  376.   if (getxco(tokens[0],&newx) || getyco(tokens[1],&newy)) return;
  377.   gograph(data);
  378.   data->realx=(double)newx;
  379.   data->realy=(double)newy;
  380.   turmove(data->graphxy.xcoord=newx,data->graphxy.ycoord=newy);
  381.   gotext(data);
  382.   }
  383.  
  384.  
  385. /* Set color */
  386. XCICMD colorcmd(int cmd, char far *cmds,struct udata *data)
  387.   {
  388.   int col;
  389.   if (cmd)
  390.     {
  391.     printf("Set color\n");
  392.     return;
  393.     }
  394.   if (parse(cmds)!=1) synerr;
  395.   if (getcolor(tokens[0],&col)) return;
  396.   gograph(data);
  397.   data->color=col;
  398.   _setcolor(col);
  399.   gotext(data);
  400.   }
  401.  
  402.  
  403.  
  404. /* Clear screen */
  405. XCICMD clearcmd(int cmd, char far *cmds,struct udata *data)
  406.   {
  407.   if (cmd)
  408.     {
  409.     printf("Clear the screen\n");
  410.     return;
  411.     }
  412.     NOARG;
  413.   gograph(data);
  414.   _moveto(0,0);
  415.   _clearscreen(_GCLEARSCREEN);
  416.   data->heading=0;
  417.   data->graphxy.xcoord=data->graphxy.ycoord=0;
  418.   data->realx=data->realy=0.0;
  419.   gotext(data);
  420.   }
  421.  
  422. /* pen up (change mode) */
  423. XCICMD penupcmd(int cmd, char far *cmds,struct udata *data)
  424.   {
  425.   if (cmd)
  426.     {
  427.     printf("Cause the turtle not to draw\n");
  428.     return;
  429.     }
  430.   NOARG;
  431.   data->mode=1;
  432.   }
  433.  
  434. /* pen down (change mode) */
  435. XCICMD pendowncmd(int cmd, char far *cmds,struct udata *data)
  436.   {
  437.   if (cmd)
  438.     {
  439.     printf("Cause the turtle to draw\n");
  440.     return;
  441.     }
  442.   NOARG;
  443.   data->mode=0;
  444.   }
  445.  
  446. /* change background color */
  447. XCICMD backgcmd(int cmd, char far *cmds,struct udata *data)
  448.   {
  449.   long col;
  450.   int index;
  451.   if (cmd)
  452.     {
  453.     printf("Set the background color\n");
  454.     return;
  455.     }
  456.   if (parse(cmds)!=1) synerr;
  457.   getcolor(tokens[0],&index);
  458.   gograph(data);
  459.   col=_remappalette(index,0L);
  460.   _remappalette(index,col);
  461.   data->backcolor=col;
  462.   _setbkcolor(col);
  463.   gotext(data);
  464.   }
  465.  
  466.  
  467. /* Set cursor to 0,0 */
  468. XCICMD homecmd(int cmd, char far *cmds,struct udata *data)
  469.   {
  470.   char cmdline[10];
  471.   if (cmd)
  472.     {
  473.     printf("Move the turtle to the top left corner\n");
  474.     return;
  475.     }
  476.   NOARG;
  477.   strcpy(cmdline,"0 0\n");
  478.   data->heading=0;
  479. /* simulate XCI command */
  480. /* NOTE: you shouldn't do: setxycmd(0,"0 0\n",data)
  481.    the parse algorithm will chop up the command line
  482.    causing this to only work once */
  483.   setxycmd(0,cmdline,data);
  484.   }
  485.  
  486. /* Turn heading */
  487. XCICMD turncmd(int cmd, char far *cmds,struct udata *data)
  488.   {
  489.   int turn;
  490.   if (cmd)
  491.     {
  492.     printf("Turn the turtle\n");
  493.     return;
  494.     }
  495.   if (parse(cmds)!=1) synerr;
  496.   if (gethead(tokens[0],&turn)) return;
  497.   data->heading=turn;
  498.   }
  499.  
  500. #define PI ((double)3.1415926536)
  501. /* convert degrees to radians */
  502. #define deg2rad(deg) (((double) deg)*(PI/180.0))
  503. /* quick signum function */
  504. #define SGN(a) ((a)<0?-1:(a)>0?1:0)
  505.  
  506. /* move turtle ahead */
  507. XCICMD movecmd(int cmd, char far *cmds,struct udata *data)
  508.   {
  509.   int amt,x1,y1;
  510.   double rads,tempreal;
  511.   if (cmd)
  512.     {
  513.     printf("Move the turtle\n");
  514.     return;
  515.     }
  516.   if (parse(cmds)!=1) synerr;
  517.   getval(tokens[0],0,0,0,&amt);
  518.   if (!amt) return;
  519. /* Get heading in radians */
  520.   rads=deg2rad(data->heading);
  521.  
  522. /* calculate new X & Y
  523.    (cos=x/r    sin=y/r) */
  524.   data->realx+=amt*cos(rads);
  525.   x1=(int)(data->realx+.5*SGN(data->realx));
  526.   data->realy+=amt*sin(rads);
  527.   y1=(int)(data->realy+.5*SGN(data->realy));
  528.   gograph(data);
  529.   turmove(data->graphxy.xcoord=x1,data->graphxy.ycoord=y1);
  530.   gotext(data);
  531.   }
  532.  
  533.  
  534. /* repeat a command file */
  535. XCICMD rptcmd(int cmd, char far *cmds,struct udata *data)
  536.   {
  537.   int count;
  538.   char fn[67];
  539.   if (cmd)
  540.     {
  541.     printf("Repeat a command file\n");
  542.     return;
  543.     }
  544.   if (parse(cmds)!=2) synerr;
  545.   getval(tokens[0],0,0,0,&count);
  546.   if (count<=0)
  547.     {
  548.     printf("Error: count must be >=0\n");
  549.     return;
  550.     }
  551.   strcpy(fn,tokens[1]);
  552.   while (count--) dofunc(0,fn,data);
  553.   }
  554.  
  555.  
  556. /* delay a specified number of .1 seconds */
  557. XCICMD delaycmd(int cmd, char far *cmds,struct udata *data)
  558.   {
  559.   int amt;
  560.   unsigned long t;
  561.   REGS16 r;
  562.   if (cmd)
  563.     {
  564.     printf("Delay for a time (in .1 second increments)\n");
  565.     return;
  566.     }
  567.   if (parse(cmds)!=1) synerr;
  568.   getval(tokens[0],0,0,0,&amt);
  569.   if (amt<0)
  570.     {
  571.     amt=0;
  572.     printf("Error: delay time must be >0\n");
  573.     }
  574.   if (!amt) return;
  575.   t=amt*100000L;
  576.   r.ax=0x8600;
  577.   r.cx=(t&0xFFFF0000)>>16;
  578.   r.dx=t&0xffff;
  579.  
  580. /* Use INT 15H Function 86H to delay -- DOS extender doesn't
  581.   support this directly. We must use DosRealIntr() */
  582.   DosRealIntr(0x15,&r,0L,0);
  583.   }
  584.  
  585.  
  586.  
  587. /* If command */
  588. /* Use XCI do and goto commands to perform do and goto */
  589. XCICMD ifcmd(int cmd, char far *cmds,struct udata *data)
  590.   {
  591.   int bool;
  592.   char fn[67];
  593.   if (cmd)
  594.     {
  595.     printf("Conditionally execute a commmand file\n");
  596.     return;
  597.     }
  598.   if (parse(cmds)!=3) synerr;
  599.   if (getval(tokens[0],0,0,0,&bool)) return;
  600.   if (bool)
  601.     {
  602.     if (!stricmp(tokens[1],"THEN")&&!stricmp(tokens[2],"EXIT"))
  603.       {
  604. /* goto EOF of current file -- XCI thinks it is done */
  605.       fseek(xci_infile,0L,SEEK_END);
  606.       return;
  607.       }
  608.     if (!stricmp(tokens[1],"DO"))
  609.       {
  610.       strcpy(fn,tokens[2]);
  611.       dofunc(0,fn,data);
  612.       return;
  613.       }
  614.     if (!stricmp(tokens[1],"GOTO"))
  615.       {
  616.       gotofunc(0,tokens[2],data);
  617.       return;
  618.       }
  619.     synerr;
  620.     }
  621.   }
  622.  
  623.  
  624. /* Set a variable */
  625. XCICMD setcmd(int cmd, char far *cmds,struct udata *data)
  626.   {
  627.   int val;
  628.   if (cmd)
  629.     {
  630.     printf("Set a variable\n");
  631.     return;
  632.     }
  633.   if (parse(cmds)!=2) synerr;
  634.   if (strlen(tokens[0])!=1||!isalpha(*tokens[0]))
  635.     {
  636.     printf("Variables must be A-Z\n");
  637.     return;
  638.     }
  639.   getval(tokens[1],0,0,0,&val);
  640.   data->vars[toupper(*tokens[0])-'A']=val;
  641.   }
  642.  
  643. /* Stack for PUSH/POP commands */
  644. static int intstack[512];
  645. static int intstackp=0;
  646.  
  647. XCICMD pushcmd(int cmd, char far *cmds,struct udata *data)
  648.   {
  649.   int val;
  650.   if (cmd)
  651.     {
  652.     printf("Push a value on the stack\n");
  653.     return;
  654.     }
  655.   if (parse(cmds)!=1) synerr;
  656.   getval(tokens[0],0,0,0,&val);
  657.   if (intstackp==sizeof(intstack)/sizeof(int))
  658.     printf("Stack overflow\n");
  659.   else
  660.     intstack[intstackp++]=val;
  661.   }
  662.  
  663.  
  664. XCICMD popcmd(int cmd, char far *cmds,struct udata *data)
  665.   {
  666.   int val;
  667.   if (cmd)
  668.     {
  669.     printf("Pop the top of the stack to a variable\n");
  670.     return;
  671.     }
  672.   if (parse(cmds)!=1) synerr;
  673.   if (strlen(tokens[0])!=1||!isalpha(*tokens[0]))
  674.     {
  675.     printf("Variables must be A-Z\n");
  676.     return;
  677.     }
  678.   if (!intstackp)
  679.     printf("Nothing to pop\n");
  680.   else
  681.     data->vars[toupper(*tokens[0])-'A']=intstack[--intstackp];
  682.   }
  683.  
  684.  
  685.  
  686. /* Store the graphics screen to a buffer */
  687. XCICMD stocmd(int cmd, char far *cmds,struct udata *data)
  688.   {
  689.   int buf;
  690.   if (cmd)
  691.     {
  692.     printf("Store the screen to memory\n");
  693.     return;
  694.     }
  695.   if (parse(cmds)!=1) synerr;
  696.   if (getval(tokens[0],0,1,10,&buf)) return;
  697.   if (!data->store[--buf])
  698.      {
  699. /* allocate storage if needed */
  700.      data->store[buf]=malloc((unsigned)64000);
  701.      if (!data->store[buf])
  702.         {
  703.         printf("Out of memory\n");
  704.         return;
  705.         }
  706.       }
  707. /* copy to the screen if in graphics mode, or to graphics
  708.    buffer if not */
  709.   memcpy(data->store[buf],data->store[10+data->textgraph],
  710.          (unsigned)64000);
  711.   }
  712.  
  713.  
  714. /* Restore a buffer to the screen */
  715. XCICMD rclcmd(int cmd, char far *cmds,struct udata *data)
  716.   {
  717.   int buf;
  718.   if (cmd)
  719.     {
  720.     printf("Recall a screen from memory\n");
  721.     return;
  722.     }
  723.   if (parse(cmds)!=1) synerr;
  724.   if (getval(tokens[0],0,1,10,&buf)) return;
  725.   if (!data->store[--buf])
  726.      {
  727.      printf("Buffer %d empty\n",buf+1);
  728.      return;
  729.      }
  730.   memcpy(data->store[10+data->textgraph],data->store[buf],
  731.          (unsigned)64000);
  732.   }
  733.  
  734.  
  735. /* Fill a region */
  736. XCICMD fillcmd(int cmd, char far *cmds,struct udata *data)
  737.   {
  738.   int buf;
  739.   if (cmd)
  740.     {
  741.     printf("Fill a region\n");
  742.     return;
  743.     }
  744.   NOARG;
  745.   gograph(data);
  746.   _floodfill(data->graphxy.xcoord,data->graphxy.ycoord,data->color);
  747.   gotext(data);
  748.   }
  749.  
  750.  
  751. /* Write text */
  752. XCICMD textcmd(int cmd, char far *cmds,struct udata *data)
  753.   {
  754.   int buf;
  755.   if (cmd)
  756.     {
  757.     printf("Print text\n");
  758.     return;
  759.     }
  760.   gograph(data);
  761.   _settextcolor(data->tcolor);
  762. /* calculate text cursor based on graphics cursor */
  763.   _settextposition(data->graphxy.xcoord/8,data->graphxy.ycoord/8);
  764.   _outtext(cmds);
  765.   gotext(data);
  766.   }
  767.  
  768. /* prompt user with string */
  769. /* if string starts with ~ then don't add a new line */
  770. XCICMD promptcmd(int cmd, char far *cmds,struct udata *data)
  771.   {
  772.   int buf;
  773.   if (cmd||!*cmds)
  774.     {
  775.     printf("Prompt user\n");
  776.     return;
  777.     }
  778.   turtleprompt(cmds+(*cmds=='~'));
  779.   if (*cmds!='~') turtleprompt("\n");
  780.   }
  781.  
  782.  
  783.  
  784. /* Set text color */
  785. XCICMD textccmd(int cmd, char far *cmds,struct udata *data)
  786.   {
  787.   int col;
  788.   if (cmd)
  789.     {
  790.     printf("Set text color\n");
  791.     return;
  792.     }
  793.   if (parse(cmds)!=1) synerr;
  794.   if (getval(tokens[0],data->tcolor,0,15,&col)) return;
  795.   data->tcolor=col;
  796.   }
  797.  
  798.  
  799.  
  800. /* Install commands. This is called by the XCI startup
  801.    function in TURTLE.C. It is in this file so TURTLE.C
  802.    doesn't need prototypes for each command function */
  803. int installcmds()
  804.   {
  805. /* enable XCI's internal goto command */
  806.   if (addcmd("goto",gotofunc)) return 1;
  807.   if (addcmd("cd",cdcmd)) return 1;
  808.   if (addcmd("dir",dircmd)) return 1;
  809.   if (addcmd("dos",doscmd)) return 1;
  810.   if (addcmd("edit",editcmd)) return 1;
  811.   if (addcmd("repeat",rptcmd)) return 1;
  812.   if (addcmd("if",ifcmd)) return 1;
  813.   if (addcmd("set",setcmd)) return 1;
  814.   if (addcmd("sto",stocmd)) return 1;
  815.   if (addcmd("rcl",rclcmd)) return 1;
  816.   if (addcmd("push",pushcmd)) return 1;
  817.   if (addcmd("pop",popcmd)) return 1;
  818.   if (addcmd("delay",delaycmd)) return 1;
  819.   if (addcmd("prompt",promptcmd)) return 1;
  820.   if (addcmd("show",showcmd)) return 1;
  821.   if (addcmd("fill",fillcmd)) return 1;
  822.   if (addcmd("textcolor",textccmd)) return 1;
  823.   if (addcmd("text",textcmd)) return 1;
  824.   if (addcmd("setx",setxcmd)) return 1;
  825.   if (addcmd("sety",setycmd)) return 1;
  826.   if (addcmd("setxy",setxycmd)) return 1;
  827.   if (addcmd("background",backgcmd)) return 1;
  828.   if (addcmd("pencolor",colorcmd)) return 1;
  829.   if (addcmd("clear",clearcmd)) return 1;
  830.   if (addcmd("home",homecmd)) return 1;
  831.   if (addcmd("penup",penupcmd)) return 1;
  832.   if (addcmd("pendown",pendowncmd)) return 1;
  833.   if (addcmd("turn",turncmd)) return 1;
  834.   if (addcmd("move",movecmd)) return 1;
  835.   return 0;
  836.   }
  837.